package cc.android.testapp.ui;

import android.Manifest;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.util.Pair;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import org.json.JSONArray;
import org.json.JSONObject;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;

import cc.android.testapp.R;
import cc.android.testapp.cfg.Config;
import cc.android.testapp.cfg.ConfigHelper;
import cc.android.testapp.permission.PermissionHelper;
import cc.android.testapp.permission.PermissionInterface;
import cc.android.testapp.ui.applist.AppListActivity;
import cc.android.testapp.ui.binding.ActivityMainBinding;
import cc.android.testapp.ui.part.HisEditText;
import cc.android.testapp.util.CLog;
import cc.android.testapp.util.RenameYouhua;
import cc.android.testapp.xp.hooker.textmodify.ViewPropDialog;
import cc.commons.util.FileUtil;
import cc.commons.util.StringUtil;
import cc.commons.util.reflect.FieldUtil;

public class MainActivity extends AppCompatActivity implements PermissionInterface, View.OnClickListener {

    private File mStorage;
    private static final File mfile_ly = new File(Environment.getExternalStorageDirectory(),
            "Download/config/" + Config.MODULE_PACKAGE_NAME + "/ly.json");
    private static final File mfile_lyformat = new File(Environment.getExternalStorageDirectory(),
            "Download/config/" + Config.MODULE_PACKAGE_NAME + "/ly_format.txt");

    private ActivityMainBinding bind;

    private final HashMap<Integer, Pair<String, String>> mItems = new HashMap<>();

    /**
     * 0:经度,1:纬度
     *
     * @return
     */
    public double[] getRedirectLoc() {
        int i = 0;
        double[] tLoc = new double[2];
        for (TextView sTView : Arrays.asList(bind.etLocLongitude, bind.etLocLatitude)) {
            String tContent = sTView.getText().toString();
            if (StringUtil.isBlank(tContent)) {
                tLoc[i] = 0D;
            } else {
                tLoc[i] = Double.parseDouble(tContent);
                sTView.setText(String.valueOf(tLoc[i]));
            }
            i++;
        }

        return tLoc;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        bind = new ActivityMainBinding(getLayoutInflater().inflate(R.layout.activity_main, null));
        setContentView(bind.getRoot());

        this.mStorage = new File(Environment.getExternalStorageDirectory(), "Download");
        PermissionHelper mPermissionHelper = new PermissionHelper(this, this);
        mPermissionHelper.requestPermissions();

        FieldUtil.getDeclaredField(bind.getClass(), field -> Button.class.isAssignableFrom(field.getType())).forEach(ff -> {
            Object tButton = FieldUtil.getFieldValue(ff, bind);
            if (tButton != null) ((Button) tButton).setOnClickListener(MainActivity.this);
        });
        ((Button) findViewById(R.id.btn_rename_yh_name)).setOnClickListener(this);
        ((Button) findViewById(R.id.btn_rename_fugua)).setOnClickListener(this);

        loadConfig();
        this.updateHookStatus();
        findViewById(R.id.img_test).setOnClickListener((v) -> {
            if (Config.enableViewCheck() && !ViewPropDialog.isShown())
                ViewPropDialog.appendShowView(MainActivity.this.getWindow().getDecorView());
        });
    }

    public void loadConfig() {
        Config.updateConfig();
        JSONObject tConfig = Config.getConfig();

        String tStr;
        JSONObject tJson = tConfig.optJSONObject("pda");
        if (tJson != null) {
            double tValue = tJson.optDouble(Config.KEY_LOCATION_JD, 0D);
            if (!Double.isNaN(tValue) && tValue != 0D)
                bind.etLocLongitude.setText(String.valueOf(tValue));
            tValue = tJson.optDouble(Config.KEY_LOCATION_WD, 0D);
            if (!Double.isNaN(tValue) && tValue != 0D)
                bind.etLocLatitude.setText(String.valueOf(tValue));
            tStr = tJson.optString(Config.KEY_ADDRESS, "");
            if (StringUtil.isNotEmpty(tStr)) bind.etAddress.setText(tStr);
            tStr = tJson.optString(Config.KEY_DEVICE_ID, "");
            if (StringUtil.isNotEmpty(tStr)) bind.etDeviceId.setText(tStr);
        }

        tJson = tConfig.optJSONObject("track");
        if (tJson != null) {
            bind.hisTraceClassMore.loadFromJson(tJson);
            bind.hisTraceMethodMore.loadFromJson(tJson);
        }

        tJson = tConfig.optJSONObject("cmtt");
        if (tJson != null) {
            bind.btnLocSwitch.enable = tJson.optBoolean("enable", false);
            bind.btnLocSwitch.updateText();
        }
    }

    public void updateHookStatus() {
        String tMsg = this.isModuleEnabled() ? "模块已经启用" : "模块未启用";
        bind.tvHookResult.setText(tMsg);
        if (this.isModuleEnabled()) bind.tvHookResult.setTextColor(Color.parseColor("#FF000000"));
        else bind.tvHookResult.setTextColor(Color.parseColor("#FFFF0000"));
    }

    public void syncRemoteConfig() {
        Intent tIntent = new Intent(ConfigHelper.MSG_UPDATE_CONFIG);
        sendBroadcast(tIntent);
    }

    public void onClick(View pView) {
        boolean tSave = false;
        try {
            if (pView.getId() == R.id.btn_loc_confirm) {
                JSONObject tPdaCfg = Config.getOrCreateSubCfg("pda");

                double[] tLoc = getRedirectLoc();
                tPdaCfg.put(Config.KEY_LOCATION_JD, tLoc[0]);
                tPdaCfg.put(Config.KEY_LOCATION_WD, tLoc[1]);

                tPdaCfg.put(Config.KEY_ADDRESS, bind.etAddress.getText());
                tPdaCfg.put(Config.KEY_DEVICE_ID, bind.etDeviceId.getText());
                tSave = true;

                Toast.makeText(this, "已经设置坐标", Toast.LENGTH_SHORT).show();
            } else if (pView.getId() == R.id.btn_loc_switch) {
                JSONObject tPdaCfg = Config.getOrCreateSubCfg("cmtt");
                tPdaCfg.put("enable", !tPdaCfg.optBoolean("enable"));
                tSave = true;
                bind.btnLocSwitch.switchStat();
            } else if (pView.getId() == R.id.btn_loc_clear) {
                bind.etLocLongitude.setText("119.");
                bind.etLocLatitude.setText("29.");
                return;
            } else if (pView.getId() == R.id.btn_collect_box_img) {
                RenameYouhua.tryShow(this);
                return;
            } else if (pView.getId() == R.id.btn_restore_box_img) {
                BoxNameDialog.handleRestore(this);
                return;
            } else if (pView.getId() == R.id.btn_trace_confirm) {
                JSONObject tCfg = Config.getOrCreateSubCfg("track");
                for (HisEditText s : bind.hisEdits) {
                    s.pushToHistroy();
                    s.saveToJson(tCfg);
                }
                tSave = true;
                Toast.makeText(this, "已经设置跟踪", Toast.LENGTH_SHORT).show();
            } else if (pView.getId() == R.id.btn_trace_clean) {
                JSONObject tCfg = Config.getOrCreateSubCfg("track");
                for (HisEditText s : bind.hisEdits) {
                    s.setText("");
                    s.saveToJson(tCfg);
                }
                tSave = true;
                Toast.makeText(this, "已经取消跟踪", Toast.LENGTH_SHORT).show();
            } else if (pView.getId() == R.id.btn_rename_yh_name) {
                RenameYouhua.renameYHName(this, this.mStorage);
            } else if (pView.getId() == R.id.btn_caldis) {
                try {
                    JSONObject tJson = new JSONObject(FileUtil.readContent(mfile_ly, "UTF-8"));
                    JSONArray tPoints = tJson.getJSONArray("points");
                    String[] tParts = tJson.getString("OPTICALSECTIONROUTE").split("&lt;&gt;");
                    int index = 1;
                    double prelat = tPoints.getJSONObject(0).getDouble("y");
                    double prelon = tPoints.getJSONObject(0).getDouble("x");
                    double tTotlaDis = 0;
                    StringBuilder tSBulder = new StringBuilder();
                    while (index < tPoints.length()) {
                        JSONObject tPoint = tPoints.getJSONObject(index);
                        double lat = tPoint.getDouble("y");
                        double lon = tPoint.getDouble("x");
                        double tDis = calDis(prelat, prelon, lat, lon);
                        tTotlaDis += tDis;
                        tSBulder.append(String.format("%6.1f %5.1f  ", tTotlaDis, tDis));
                        tSBulder.append(String.format("(%9.6f,%10.6f)-(%9.6f,%10.6f)  ", prelat, prelon, lat, lon));
                        if (index - 1 < tParts.length) tSBulder.append(tParts[index - 1]);
                        tSBulder.append("\r\n");

                        prelat = lat;
                        prelon = lon;

                        index++;
                    }

                    FileUtil.writeData(mfile_lyformat, tSBulder.toString().getBytes(StandardCharsets.UTF_8));
                    Toast.makeText(this, "处理完毕", Toast.LENGTH_SHORT).show();
                } catch (Throwable e) {
                    Toast.makeText(this, "报错了: " + e.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
                }
            } else if (pView.getId() == R.id.btn_rename_fugua) {
                RenameYouhua.renameFuGua(this, this.mStorage);
            }
        } catch (Throwable e) {
            CLog.log("Error on set config from ui: " + e.getLocalizedMessage());
            Toast.makeText(this, "处理点击时报错了: " + e.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
        }

        if (tSave) {
            Config.saveConfig();
            syncRemoteConfig();
        }
    }

    public static double calDis(double lat1, double lon1, double lat2, double lon2) {
        double dLat = Math.toRadians(lat2 - lat1);
        double dLon = Math.toRadians(lon2 - lon1);

        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
                Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
                        Math.sin(dLon / 2) * Math.sin(dLon / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

        return 6371000 * c;
    }

    @Override
    public int getPermissionsRequestCode() {
        return 0;
    }

    @Override
    public String[] getPermissions() {
        return new String[]{
                Manifest.permission.ACCESS_COARSE_LOCATION,
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
        };
    }

    @Override
    public void requestPermissionsSuccess() {

    }

    @Override
    public void requestPermissionsFail() {

    }

    public boolean isModuleEnabled() {
        return false;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu pMenu) {
        getMenuInflater().inflate(R.menu.menu, pMenu);
        this.mItems.put(R.id.menu_enable_edit, new Pair<>(Config.KEY_ENABLE_TEXTEDIT, "文字编辑"));
        this.mItems.put(R.id.menu_enable_view_ckeck, new Pair<>(Config.KEY_ENABLE_VIEWCHECK, "视图查看"));
        this.mItems.put(R.id.menu_enable_fileLog, new Pair<>(Config.KEY_ENABLE_FILELOG, "文件日志"));
        this.mItems.put(R.id.menu_enable_log_redirect, new Pair<>(Config.KEY_REDIRECT_LOG, "日志重定向"));

        this.mItems.forEach((k, v) -> {
            if (Config.getConfig().optBoolean(v.first, false)) {
                Config.setProp(v.first, false, false);
                onOptionsItemSelected(pMenu.findItem(k));
            }
        });

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem pItem) {
        boolean tEnable;

        Pair<String, String> tItem = this.mItems.get(pItem.getItemId());
        if (tItem != null) {
            Config.setProp(tItem.first, tEnable = !Config.getConfig().optBoolean(tItem.first, false), true);
            pItem.setTitle((tEnable ? "关闭" : "启用") + tItem.second);
            syncRemoteConfig();
        } else if (pItem.getItemId() == R.id.menu_reload_config) {
            loadConfig();
            Toast.makeText(this, "操作完成", Toast.LENGTH_SHORT).show();
        } else if (pItem.getItemId() == R.id.menu_app_list) {
            startActivity(new Intent(this, AppListActivity.class));
        }
        return super.onOptionsItemSelected(pItem);
    }

}
